home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / mmgr / portalmem.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-27  |  22.9 KB  |  943 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    portalmem.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    backend portal memory context management stuff
  7.  *
  8.  *   INTERNAL UTILITY ROUTINES
  9.  *    CreateNewBlankPortal, ComputePortalNameHashIndex,
  10.  *    ComputePortalHashIndex, PortalHasPortalName, PortalDump,
  11.  *    DumpPortals, PortalVariableMemoryAlloc,
  12.  *    PortalVariableMemoryFree, PortalVariableMemoryRealloc,
  13.  *    PortalVariableMemoryGetName, PortalVariableMemoryDump,
  14.  *    PortalHeapMemoryAlloc, PortalHeapMemoryFree,
  15.  *    PortalHeapMemoryRealloc, PortalHeapMemoryGetName,
  16.  *    PortalHeapMemoryDump
  17.  *    
  18.  *   INTERFACE ROUTINES
  19.  *    EnablePortalManager
  20.  *    GetPortalByName
  21.  *    BlankPortalAssignName
  22.  *    PortalSetQuery
  23.  *    PortalGetQueryDesc
  24.  *    PortalGetState
  25.  *    CreatePortal
  26.  *    PortalDestroy
  27.  *    PortalResetHeapMemory
  28.  *    StartPortalAllocMode
  29.  *    EndPortalAllocMode
  30.  *    PortalGetVariableMemory
  31.  *    PortalGetHeapMemory
  32.  *    PortalVariableMemoryGetPortal
  33.  *    PortalHeapMemoryGetPortal
  34.  *    PortalVariableMemoryGetHeapMemory
  35.  *    PortalHeapMemoryGetVariableMemory
  36.  *
  37.  *   NOTES
  38.  *    Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer").
  39.  *    When a PQexec() routine is run, the resulting tuples
  40.  *    find their way into a "PortalEntry".  The contents of the resulting
  41.  *    "PortalEntry" can then be inspected by other PQxxx functions.
  42.  *
  43.  *    A "Portal" is a structure used to keep track of queries of the
  44.  *    form:
  45.  *        retrieve portal FOO ( blah... ) where blah...
  46.  *
  47.  *    When the backend sees a "retrieve portal" query, it allocates
  48.  *    a "PortalD" structure, plans the query and then stores the query
  49.  *    in the portal without executing it.  Later, when the backend
  50.  *    sees a
  51.  *        fetch 1 into FOO
  52.  *
  53.  *    the system looks up the portal named "FOO" in the portal table,
  54.  *    gets the planned query and then calls the executor with a feature of
  55.  *    '(EXEC_FOR 1).  The executor then runs the query and returns a single
  56.  *    tuple.  The problem is that we have to hold onto the state of the
  57.  *    portal query until we see a "close p".  This means we have to be
  58.  *    careful about memory management.
  59.  *
  60.  *    Having said all that, here is what a PortalD currently looks like:
  61.  *
  62.  * struct PortalD {
  63.  *    String                name;
  64.  *    classObj(PortalVariableMemory)    variable;
  65.  *    classObj(PortalHeapMemory)    heap;
  66.  *    List                queryDesc;
  67.  *    EState                state;
  68.  *    void                (*cleanup) ARGS((Portal portal));
  69.  * };
  70.  *
  71.  *    I hope this makes things clearer to whoever reads this -cim 2/22/91
  72.  *
  73.  *    Here is an old comment taken from nodes/mnodes.h
  74.  *
  75.  * MemoryContext --
  76.  *    A logical context in which memory allocations occur.
  77.  *
  78.  * The types of memory contexts can be thought of as members of the
  79.  * following inheritance hierarchy with properties summarized below.
  80.  *
  81.  *            Node
  82.  *            |
  83.  *        MemoryContext___
  84.  *        /        \
  85.  *    GlobalMemory    PortalMemoryContext
  86.  *            /        \
  87.  *    PortalVariableMemory    PortalHeapMemory
  88.  *
  89.  *            Flushed at    Flushed at    Checkpoints
  90.  *            Transaction    Portal
  91.  *            Commit        Close
  92.  *
  93.  * GlobalMemory            n        n        n
  94.  * PortalVariableMemory        n        y        n
  95.  * PortalHeapMemory        y        y        y *    
  96.  *
  97.  *   IDENTIFICATION
  98.  *    $Header: /private/postgres/src/utils/mmgr/RCS/portalmem.c,v 1.21 1992/08/18 18:27:16 mer Exp $
  99.  * ----------------------------------------------------------------
  100.  */
  101.  
  102. #include "tmp/c.h"
  103.  
  104. RcsId("$Header: /private/postgres/src/utils/mmgr/RCS/portalmem.c,v 1.21 1992/08/18 18:27:16 mer Exp $");
  105.  
  106. #include <strings.h>    /* for strlen, strncpy */
  107.  
  108. #include "tmp/hasht.h"
  109. #include "utils/module.h"
  110. #include "utils/excid.h"    /* for Unimplemented */
  111. #include "utils/log.h"
  112. #include "utils/mcxt.h"
  113. #include "utils/hsearch.h"
  114.  
  115. #include "nodes/mnodes.h"
  116. #include "nodes/nodes.h"
  117. #include "nodes/pg_lisp.h"
  118. #include "nodes/execnodes.h"    /* for EState */
  119. #include "tags.h"
  120.  
  121. #include "tmp/portal.h"
  122.  
  123. /* ----------------
  124.  *       ALLOCFREE_ERROR_ABORT
  125.  *       define this if you want a core dump when you try to
  126.  *       free memory already freed -cim 2/9/91
  127.  * ----------------
  128.  */
  129. #undef ALLOCFREE_ERROR_ABORT
  130.  
  131. /* ----------------
  132.  *       Global state
  133.  * ----------------
  134.  */
  135.  
  136. static Count PortalManagerEnableCount = 0;
  137. #define MAX_PORTALNAME_LEN    50
  138. typedef struct portalhashent {
  139.     char portalname[MAX_PORTALNAME_LEN];
  140.     Portal portal;
  141. } PortalHashEnt;
  142.  
  143. #define PortalManagerEnabled    (PortalManagerEnableCount >= 1)
  144.  
  145. static HTAB        *PortalHashTable = NULL;
  146. #define PortalHashTableLookup(NAME, PORTAL) \
  147.     {   PortalHashEnt *hentry; Boolean found; char key[MAX_PORTALNAME_LEN]; \
  148.     bzero(key, MAX_PORTALNAME_LEN); \
  149.     sprintf(key, "%s", NAME); \
  150.     hentry = (PortalHashEnt*)hash_search(PortalHashTable, \
  151.                          key, HASH_FIND, &found); \
  152.     if (hentry == NULL) \
  153.         elog(FATAL, "error in PortalHashTable"); \
  154.     if (found) \
  155.         PORTAL = hentry->portal; \
  156.     else \
  157.         PORTAL = NULL; \
  158.     }
  159. #define PortalHashTableInsert(PORTAL) \
  160.     {   PortalHashEnt *hentry; Boolean found; char key[MAX_PORTALNAME_LEN]; \
  161.     bzero(key, MAX_PORTALNAME_LEN); \
  162.     sprintf(key, "%s", PORTAL->name); \
  163.     hentry = (PortalHashEnt*)hash_search(PortalHashTable, \
  164.                          key, HASH_ENTER, &found); \
  165.     if (hentry == NULL) \
  166.         elog(FATAL, "error in PortalHashTable"); \
  167.     if (found) \
  168.         elog(NOTICE, "trying to insert a portal name that exists."); \
  169.     hentry->portal = PORTAL; \
  170.     }
  171. #define PortalHashTableDelete(PORTAL) \
  172.     {   PortalHashEnt *hentry; Boolean found; char key[MAX_PORTALNAME_LEN]; \
  173.     bzero(key, MAX_PORTALNAME_LEN); \
  174.     sprintf(key, "%s", PORTAL->name); \
  175.     hentry = (PortalHashEnt*)hash_search(PortalHashTable, \
  176.                          key, HASH_REMOVE, &found); \
  177.     if (hentry == NULL) \
  178.         elog(FATAL, "error in PortalHashTable"); \
  179.     if (!found) \
  180.         elog(NOTICE, "trying to delete portal name that does not exist."); \
  181.     }
  182.  
  183. static GlobalMemory    PortalMemory = NULL;
  184. static char        PortalMemoryName[] = "Portal";
  185.  
  186. static Portal        BlankPortal = NULL;
  187.  
  188. /* ----------------
  189.  *     Internal class definitions
  190.  * ----------------
  191.  */
  192. typedef struct HeapMemoryBlockData {
  193.     AllocSetData    setData;
  194.     FixedItemData    itemData;
  195. } HeapMemoryBlockData;
  196.  
  197. typedef HeapMemoryBlockData    *HeapMemoryBlock;
  198.  
  199. #define HEAPMEMBLOCK(context) \
  200.     ((HeapMemoryBlock)(context)->block)
  201.  
  202. /* ----------------------------------------------------------------
  203.  *          Variable and heap memory methods
  204.  * ----------------------------------------------------------------
  205.  */
  206. /* ----------------
  207.  *    PortalVariableMemoryAlloc
  208.  * ----------------
  209.  */
  210. static Pointer
  211. PortalVariableMemoryAlloc(this, size)
  212.     PortalVariableMemory    this;
  213.     Size            size;
  214. {
  215.     return (AllocSetAlloc(&this->setData, size));
  216. }
  217.  
  218. /* ----------------
  219.  *    PortalVariableMemoryFree
  220.  * ----------------
  221.  */
  222. static void
  223. PortalVariableMemoryFree(this, pointer)
  224.     PortalVariableMemory    this;
  225.     Pointer            pointer;
  226. {
  227.     AllocSetFree(&this->setData, pointer);
  228. }
  229.  
  230. /* ----------------
  231.  *    PortalVariableMemoryRealloc
  232.  * ----------------
  233.  */
  234. static Pointer
  235. PortalVariableMemoryRealloc(this, pointer, size)
  236.     PortalVariableMemory    this;
  237.     Pointer            pointer;
  238.     Size            size;
  239. {
  240.     return (AllocSetRealloc(&this->setData, pointer, size));
  241. }
  242.  
  243. /* ----------------
  244.  *    PortalVariableMemoryGetName
  245.  * ----------------
  246.  */
  247. static String
  248. PortalVariableMemoryGetName(this)
  249.     PortalVariableMemory    this;
  250. {
  251.     return (form((int)"%s-var", PortalVariableMemoryGetPortal(this)->name));
  252. }
  253.  
  254. /* ----------------
  255.  *    PortalVariableMemoryDump
  256.  * ----------------
  257.  */
  258. static void
  259. PortalVariableMemoryDump(this)
  260.     PortalVariableMemory    this;
  261. {
  262.     printf("--\n%s:\n", PortalVariableMemoryGetName(this));
  263.     
  264.     AllocSetDump(&this->setData);    /* XXX is this the right interface */
  265. }
  266.  
  267. /* ----------------
  268.  *    PortalHeapMemoryAlloc
  269.  * ----------------
  270.  */
  271. static Pointer
  272. PortalHeapMemoryAlloc(this, size)
  273.     PortalHeapMemory    this;
  274.     Size            size;
  275. {
  276.     HeapMemoryBlock    block = HEAPMEMBLOCK(this);
  277.     
  278.     AssertState(PointerIsValid(block));
  279.     
  280.     return (AllocSetAlloc(&block->setData, size));
  281. }
  282.  
  283. /* ----------------
  284.  *    PortalHeapMemoryFree
  285.  * ----------------
  286.  */
  287. static void
  288. PortalHeapMemoryFree(this, pointer)
  289.     PortalHeapMemory    this;
  290.     Pointer            pointer;
  291. {
  292.     HeapMemoryBlock    block = HEAPMEMBLOCK(this);
  293.     
  294.     AssertState(PointerIsValid(block));
  295.     
  296.     if (AllocSetContains(&block->setData, pointer))
  297.     AllocSetFree(&block->setData, pointer);
  298.     else {
  299.     elog(NOTICE,
  300.          "PortalHeapMemoryFree: 0x%x not in alloc set!",
  301.          pointer);
  302. #ifdef ALLOCFREE_ERROR_ABORT
  303.     Assert(AllocSetContains(&block->setData, pointer));
  304. #endif ALLOCFREE_ERROR_ABORT
  305.     }
  306. }
  307.  
  308. /* ----------------
  309.  *    PortalHeapMemoryRealloc
  310.  * ----------------
  311.  */
  312. static Pointer
  313. PortalHeapMemoryRealloc(this, pointer, size)
  314.     PortalHeapMemory    this;
  315.     Pointer            pointer;
  316.     Size            size;
  317. {
  318.     HeapMemoryBlock    block = HEAPMEMBLOCK(this);
  319.     
  320.     AssertState(PointerIsValid(block));
  321.     
  322.     return (AllocSetRealloc(&block->setData, pointer, size));
  323. }
  324.  
  325. /* ----------------
  326.  *    PortalHeapMemoryGetName
  327.  * ----------------
  328.  */
  329. static String
  330. PortalHeapMemoryGetName(this)
  331.     PortalHeapMemory    this;
  332. {
  333.     return (form((int)"%s-heap", PortalHeapMemoryGetPortal(this)->name));
  334. }
  335.  
  336. /* ----------------
  337.  *    PortalHeapMemoryDump
  338.  * ----------------
  339.  */
  340. static void
  341. PortalHeapMemoryDump(this)
  342.     PortalHeapMemory    this;
  343. {
  344.     HeapMemoryBlock    block;
  345.     
  346.     printf("--\n%s:\n", PortalHeapMemoryGetName(this));
  347.     
  348.     /* XXX is this the right interface */
  349.     if (PointerIsValid(this->block))
  350.     AllocSetDump(&HEAPMEMBLOCK(this)->setData);
  351.     
  352.     /* dump the stack too */
  353.     for (block = (HeapMemoryBlock)FixedStackGetTop(&this->stackData);
  354.      PointerIsValid(block);
  355.      block = (HeapMemoryBlock)
  356.      FixedStackGetNext(&this->stackData, (Pointer)block)) {
  357.     
  358.     printf("--\n");
  359.     AllocSetDump(&block->setData);
  360.     }
  361. }
  362.  
  363. /* ----------------------------------------------------------------
  364.  *         variable / heap context method tables
  365.  * ----------------------------------------------------------------
  366.  */
  367. static MemoryContextMethodsData    PortalVariableContextMethodsData = {
  368.     PortalVariableMemoryAlloc,    /* Pointer (*)(this, uint32)    palloc */
  369.     PortalVariableMemoryFree,    /* void (*)(this, Pointer)    pfree */
  370.     PortalVariableMemoryRealloc,/* Pointer (*)(this, Pointer)    repalloc */
  371.     PortalVariableMemoryGetName,/* String (*)(this)        getName */
  372.     PortalVariableMemoryDump    /* void (*)(this)        dump */
  373.     };
  374.     
  375. static MemoryContextMethodsData    PortalHeapContextMethodsData = {
  376.     PortalHeapMemoryAlloc,    /* Pointer (*)(this, uint32)    palloc */
  377.     PortalHeapMemoryFree,    /* void (*)(this, Pointer)    pfree */
  378.     PortalHeapMemoryRealloc,    /* Pointer (*)(this, Pointer)    repalloc */
  379.     PortalHeapMemoryGetName,    /* String (*)(this)        getName */
  380.     PortalHeapMemoryDump    /* void (*)(this)        dump */
  381.     };
  382.     
  383.  
  384. /* ----------------------------------------------------------------
  385.  *          private internal support routines
  386.  * ----------------------------------------------------------------
  387.  */
  388. /* ----------------
  389.  *    CreateNewBlankPortal
  390.  * ----------------
  391.  */
  392. static void
  393. CreateNewBlankPortal()
  394. {
  395.     Portal    portal;
  396.     uint16    length;
  397.     
  398.     AssertState(!PortalIsValid(BlankPortal));
  399.     
  400.     /*
  401.      * make new portal structure
  402.      */
  403.     portal = (Portal)
  404.     MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal);
  405.     
  406.     /*
  407.      * initialize portal variable context
  408.      */
  409.     NodeSetTag((Node)&portal->variable, classTag(PortalVariableMemory));
  410.     AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0);
  411.     portal->variable.method = &PortalVariableContextMethodsData;
  412.     
  413.     /*
  414.      * initialize portal heap context
  415.      */
  416.     NodeSetTag((Node)&portal->heap, classTag(PortalHeapMemory));
  417.     portal->heap.block = NULL;
  418.     FixedStackInit(&portal->heap.stackData,
  419.            offsetof (HeapMemoryBlockData, itemData));
  420.     portal->heap.method = &PortalHeapContextMethodsData;
  421.     
  422.     /*
  423.      * set bogus portal name
  424.      */
  425.     portal->name = "** Blank Portal **";
  426.     
  427.     /* initialize portal query */
  428.     portal->queryDesc = LispNil;
  429.     portal->state = NULL;
  430.     portal->cleanup = NULL;
  431.     
  432.     /*
  433.      * install blank portal
  434.      */
  435.     BlankPortal = portal;
  436. }
  437.  
  438. bool
  439. PortalNameIsSpecial(pname)
  440.     String pname;
  441. {
  442.     if (strcmp(pname, VACPNAME) == 0)
  443.     return true;
  444.     return false;
  445. }
  446.  
  447. /*
  448.  * This routine is used to collect all portals created in this xaction
  449.  * and then destroy them.  There is a little trickiness required as a
  450.  * result of the dynamic hashing interface to getting every hash entry
  451.  * sequentially.  Its use of static variables requires that we get every
  452.  * entry *before* we destroy anything (destroying updates the hashtable
  453.  * and screws up the sequential walk of the table). -mer 17 Aug 1992
  454.  */
  455. void
  456. CollectNamedPortals(portalP, destroy)
  457.     Portal *portalP;
  458.     int    destroy;
  459. {
  460.     static Portal *portalList = (Portal *)NULL;
  461.     static int    listIndex = 0;
  462.     static int    maxIndex = 9;
  463.  
  464.     if (portalList == (Portal *)NULL)
  465.     portalList = (Portal *)malloc(10*sizeof(Portal));
  466.  
  467.     if (destroy != 0)
  468.     {
  469.     int i;
  470.  
  471.     for (i = 0; i < listIndex; i++)
  472.         PortalDestroy(portalList[i]);
  473.     listIndex = 0;
  474.     }
  475.     else
  476.     {
  477.     Assert(portalP);
  478.     Assert(*portalP);
  479.  
  480.     /*
  481.      * Don't delete special portals, up to portal creator to do this
  482.      */
  483.     if (PortalNameIsSpecial((*portalP)->name))
  484.         return;
  485.  
  486.     portalList[listIndex] = *portalP;
  487.     listIndex++;
  488.     if (listIndex == maxIndex)
  489.     {
  490.         portalList = (Portal *)
  491.         realloc(portalList, (maxIndex+11)*sizeof(Portal));
  492.         maxIndex += 10;
  493.     }
  494.     }
  495.     return;
  496. }
  497.  
  498. AtEOXact_portals()
  499. {
  500.     HashTableWalk(PortalHashTable, CollectNamedPortals, 0);
  501.     CollectNamedPortals(NULL, 1);
  502. }
  503.  
  504. /* ----------------
  505.  *    PortalDump
  506.  * ----------------
  507.  */
  508. static void
  509. PortalDump(this)
  510.     Portal    this;
  511. {
  512.     /* XXX state/argument checking here */
  513.     
  514.     PortalVariableMemoryDump(PortalGetVariableMemory(this));
  515.     PortalHeapMemoryDump(PortalGetHeapMemory(this));
  516. }
  517.  
  518. /* ----------------
  519.  *    DumpPortals
  520.  * ----------------
  521.  */
  522. static void
  523. DumpPortals()
  524. {
  525.     /* XXX state checking here */
  526.     
  527.     HashTableWalk(PortalHashTable, PortalDump, NULL);
  528. }
  529.  
  530. /* ----------------------------------------------------------------
  531.  *           public portal interface functions
  532.  * ----------------------------------------------------------------
  533.  */
  534. /* ----------------
  535.  *    EnablePortalManager
  536.  * ----------------
  537.  */
  538. void
  539. EnablePortalManager(on)
  540.     bool    on;
  541. {
  542.     static bool    processing = false;
  543.     HASHCTL ctl;
  544.     
  545.     AssertState(!processing);
  546.     AssertArg(BoolIsValid(on));
  547.     
  548.     if (BypassEnable(&PortalManagerEnableCount, on)) 
  549.     return;
  550.     
  551.     processing = true;
  552.     
  553.     if (on) {    /* initialize */
  554.     EnableMemoryContext(true);
  555.     
  556.     PortalMemory = CreateGlobalMemory(PortalMemoryName);
  557.     
  558.     ctl.keysize = MAX_PORTALNAME_LEN;
  559.     ctl.datasize = sizeof(Portal);
  560.     /* (Size) 21 est:  7 open portals or less per user */;
  561.     PortalHashTable = hash_create(21, &ctl, HASH_ELEM);
  562.     
  563.     CreateNewBlankPortal();
  564.     
  565.     } else {    /* cleanup */
  566.     if (PortalIsValid(BlankPortal)) {
  567.         PortalDestroy(BlankPortal);
  568.         MemoryContextFree((MemoryContext)PortalMemory,
  569.                   (Pointer)BlankPortal);
  570.         BlankPortal = NULL;
  571.     }
  572.     /*
  573.      * Each portal must free its non-memory resources specially.
  574.      */
  575.     HashTableWalk(PortalHashTable, PortalDestroy, NULL);
  576.     hash_destroy(PortalHashTable);
  577.     PortalHashTable = NULL;
  578.     
  579.     GlobalMemoryDestroy(PortalMemory);
  580.     PortalMemory = NULL;
  581.     
  582.     EnableMemoryContext(true);
  583.     }
  584.     
  585.     processing = false;
  586. }
  587.  
  588. /* ----------------
  589.  *    GetPortalByName
  590.  * ----------------
  591.  */
  592. Portal
  593. GetPortalByName(name)
  594.     String    name;
  595. {
  596.     Portal    portal;
  597.     
  598.     AssertState(PortalManagerEnabled);
  599.     
  600.     if (PointerIsValid(name)) {
  601.     PortalHashTableLookup(name, portal);
  602.       }
  603.     else {
  604.     if (!PortalIsValid(BlankPortal))
  605.         CreateNewBlankPortal();
  606.     portal = BlankPortal;
  607.     }
  608.     
  609.     return (portal);
  610. }
  611.  
  612. /* ----------------
  613.  *    BlankPortalAssignName
  614.  * ----------------
  615.  */
  616. Portal
  617. BlankPortalAssignName(name)
  618.     String    name;    /* XXX PortalName */
  619. {
  620.     Portal    portal;
  621.     uint16    length;
  622.     
  623.     AssertState(PortalManagerEnabled);
  624.     AssertState(PortalIsValid(BlankPortal));
  625.     AssertArg(PointerIsValid(name));    /* XXX PortalName */
  626.     
  627.     portal = GetPortalByName(name);
  628.     if (PortalIsValid(portal)) {
  629.     elog(NOTICE, "BlankPortalAssignName: portal %s already exists", name);
  630.     return (portal);
  631.     }
  632.     
  633.     /*
  634.      * remove blank portal
  635.      */
  636.     portal = BlankPortal;
  637.     BlankPortal = NULL;
  638.     
  639.     /*
  640.      * initialize portal name
  641.      */
  642.     length = 1 + strlen(name);
  643.     portal->name = (String)
  644.     MemoryContextAlloc((MemoryContext)&portal->variable, length);
  645.     
  646.     strncpy(portal->name, name, length);
  647.     
  648.     /*
  649.      * put portal in table
  650.      */
  651.     PortalHashTableInsert(portal);
  652.     
  653.     return (portal);
  654. }
  655.  
  656. /* ----------------
  657.  *    PortalSetQuery
  658.  * ----------------
  659.  */
  660. void
  661. PortalSetQuery(portal, queryDesc, state, cleanup)
  662.     Portal    portal;
  663.     List    queryDesc;
  664.     EState    state;
  665.     void    (*cleanup) ARGS((Portal portal));
  666. {
  667.     AssertState(PortalManagerEnabled);
  668.     AssertArg(PortalIsValid(portal));
  669.     AssertArg(NodeIsType((Node)queryDesc, classTag(LispList)));
  670.     AssertArg(NodeIsType((Node)state, classTag(EState)));
  671.     
  672.     portal->queryDesc = queryDesc;
  673.     portal->state = state;
  674.     portal->cleanup = cleanup;
  675. }
  676.  
  677. /* ----------------
  678.  *    PortalGetQueryDesc
  679.  * ----------------
  680.  */
  681. List    /* QueryDesc */
  682. PortalGetQueryDesc(portal)
  683.     Portal        portal;
  684. {
  685.     AssertState(PortalManagerEnabled);
  686.     AssertArg(PortalIsValid(portal));
  687.     
  688.     return (portal->queryDesc);
  689. }
  690.  
  691. /* ----------------
  692.  *    PortalGetState
  693.  * ----------------
  694.  */
  695. EState
  696. PortalGetState(portal)
  697.     Portal        portal;
  698. {
  699.     AssertState(PortalManagerEnabled);
  700.     AssertArg(PortalIsValid(portal));
  701.     
  702.     return (portal->state);
  703. }
  704.  
  705. /* ----------------
  706.  *    CreatePortal
  707.  * ----------------
  708.  */
  709. Portal
  710. CreatePortal(name)
  711.     String    name;    /* XXX PortalName */
  712. {
  713.     Portal    portal;
  714.     uint16    length;
  715.     
  716.     AssertState(PortalManagerEnabled);
  717.     AssertArg(PointerIsValid(name));    /* XXX PortalName */
  718.     
  719.     portal = GetPortalByName(name);
  720.     if (PortalIsValid(portal)) {
  721.     elog(NOTICE, "CreatePortal: portal %s already exists", name);
  722.     return (portal);
  723.     }
  724.     
  725.     /* make new portal structure */
  726.     portal = (Portal)
  727.     MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal);
  728.     
  729.     /* initialize portal variable context */
  730.     NodeSetTag((Node)&portal->variable, classTag(PortalVariableMemory));
  731.     AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0);
  732.     portal->variable.method = &PortalVariableContextMethodsData;
  733.     
  734.     /* initialize portal heap context */
  735.     NodeSetTag((Node)&portal->heap, classTag(PortalHeapMemory));
  736.     portal->heap.block = NULL;
  737.     FixedStackInit(&portal->heap.stackData,
  738.            offsetof (HeapMemoryBlockData, itemData));
  739.     portal->heap.method = &PortalHeapContextMethodsData;
  740.     
  741.     /* initialize portal name */
  742.     length = 1 + strlen(name);
  743.     portal->name = (String)
  744.     MemoryContextAlloc((MemoryContext)&portal->variable, length);
  745.     strncpy(portal->name, name, length);
  746.     
  747.     /* initialize portal query */
  748.     portal->queryDesc = LispNil;
  749.     portal->state = NULL;
  750.     portal->cleanup = NULL;
  751.     
  752.     /* put portal in table */
  753.     PortalHashTableInsert(portal);
  754.     
  755.     /* Trap(PointerIsValid(name), Unimplemented); */
  756.     return (portal);
  757. }
  758.  
  759. /* ----------------
  760.  *    PortalDestroy
  761.  * ----------------
  762.  */
  763. void
  764. PortalDestroy(portal)
  765.     Portal    portal;
  766. {
  767.     AssertState(PortalManagerEnabled);
  768.     AssertArg(PortalIsValid(portal));
  769.     
  770.     /* remove portal from table if not blank portal */
  771.     if (portal != BlankPortal)
  772.     PortalHashTableDelete(portal);
  773.     
  774.     /* reset portal */
  775.     if (PointerIsValid(portal->cleanup))
  776.     (*portal->cleanup)(portal);
  777.     
  778.     PortalResetHeapMemory(portal);
  779.     MemoryContextFree((MemoryContext)&portal->variable,
  780.               (Pointer)portal->name);
  781.     AllocSetReset(&portal->variable.setData);    /* XXX log */
  782.     
  783.     if (portal != BlankPortal)
  784.     MemoryContextFree((MemoryContext)PortalMemory, (Pointer)portal);
  785. }
  786.  
  787. /* ----------------
  788.  *    PortalResetHeapMemory
  789.  *
  790.  * Someday, Reset, Start, and End can be optimized by keeping a global
  791.  * portal module stack of free HeapMemoryBlock's.  This will make Start
  792.  * and End be fast.
  793.  * ----------------
  794.  */
  795. void
  796. PortalResetHeapMemory(portal)
  797.     Portal    portal;
  798. {
  799.     PortalHeapMemory    context;
  800.     MemoryContext    currentContext;
  801.     
  802.     context = PortalGetHeapMemory(portal);
  803.     
  804.     if (PointerIsValid(context->block)) {
  805.     /* save present context */
  806.     currentContext = MemoryContextSwitchTo((MemoryContext)context);
  807.     
  808.     do {
  809.         EndPortalAllocMode();
  810.     } while (PointerIsValid(context->block));
  811.     
  812.     /* restore context */
  813.     (void) MemoryContextSwitchTo(currentContext);
  814.     }
  815. }
  816.  
  817. /* ----------------
  818.  *    StartPortalAllocMode
  819.  * ----------------
  820.  */
  821. void
  822. StartPortalAllocMode(mode, limit)
  823.     AllocMode    mode;
  824.     Size        limit;
  825. {
  826.     PortalHeapMemory    context;
  827.     
  828.     AssertState(PortalManagerEnabled);
  829.     AssertState(IsA(CurrentMemoryContext,PortalHeapMemory));
  830.     /* AssertArg(AllocModeIsValid); */
  831.     
  832.     context = (PortalHeapMemory)CurrentMemoryContext;
  833.     
  834.     /* stack current mode */
  835.     if (PointerIsValid(context->block))
  836.     FixedStackPush(&context->stackData, context->block);
  837.     
  838.     /* allocate and initialize new block */
  839.     context->block =
  840.     MemoryContextAlloc(
  841.         (MemoryContext)PortalHeapMemoryGetVariableMemory(context),
  842.         sizeof (HeapMemoryBlockData) );
  843.     
  844.     /* XXX careful, context->block has never been stacked => bad state */
  845.     
  846.     AllocSetInit(&HEAPMEMBLOCK(context)->setData, mode, limit);
  847. }
  848.  
  849. /* ----------------
  850.  *    EndPortalAllocMode
  851.  * ----------------
  852.  */
  853. void
  854. EndPortalAllocMode()
  855. {
  856.     PortalHeapMemory    context;
  857.     
  858.     AssertState(PortalManagerEnabled);
  859.     AssertState(IsA(CurrentMemoryContext,PortalHeapMemory));
  860.     
  861.     context = (PortalHeapMemory)CurrentMemoryContext;
  862.     AssertState(PointerIsValid(context->block));    /* XXX Trap(...) */
  863.     
  864.     /* free current mode */
  865.     AllocSetReset(&HEAPMEMBLOCK(context)->setData);
  866.     MemoryContextFree((MemoryContext)PortalHeapMemoryGetVariableMemory(context),
  867.               context->block);
  868.     
  869.     /* restore previous mode */
  870.     context->block = FixedStackPop(&context->stackData);
  871. }
  872.  
  873. /* ----------------
  874.  *    PortalGetVariableMemory
  875.  * ----------------
  876.  */
  877. PortalVariableMemory
  878. PortalGetVariableMemory(portal)
  879.     Portal    portal;
  880. {
  881.     return (&portal->variable);
  882. }
  883.  
  884. /* ----------------
  885.  *    PortalGetHeapMemory
  886.  * ----------------
  887.  */
  888. PortalHeapMemory
  889. PortalGetHeapMemory(portal)
  890.     Portal    portal;
  891. {
  892.     return (&portal->heap);
  893. }
  894.  
  895. /* ----------------
  896.  *    PortalVariableMemoryGetPortal
  897.  * ----------------
  898.  */
  899. Portal
  900. PortalVariableMemoryGetPortal(context)
  901.     PortalVariableMemory    context;
  902. {
  903.     return ((Portal)((char *)context - offsetof (PortalD, variable)));
  904. }
  905.  
  906. /* ----------------
  907.  *    PortalHeapMemoryGetPortal
  908.  * ----------------
  909.  */
  910. Portal
  911. PortalHeapMemoryGetPortal(context)
  912.     PortalHeapMemory    context;
  913. {
  914.     return ((Portal)((char *)context - offsetof (PortalD, heap)));
  915. }
  916.  
  917. /* ----------------
  918.  *    PortalVariableMemoryGetHeapMemory
  919.  * ----------------
  920.  */
  921. PortalHeapMemory
  922. PortalVariableMemoryGetHeapMemory(context)
  923.     PortalVariableMemory    context;
  924. {
  925.     return ((PortalHeapMemory)((char *)context
  926.                    - offsetof (PortalD, variable)
  927.                    + offsetof (PortalD, heap)));
  928. }
  929.  
  930. /* ----------------
  931.  *    PortalHeapMemoryGetVariableMemory
  932.  * ----------------
  933.  */
  934. PortalVariableMemory
  935. PortalHeapMemoryGetVariableMemory(context)
  936.     PortalHeapMemory    context;
  937. {
  938.     return ((PortalVariableMemory)((char *)context
  939.                    - offsetof (PortalD, heap)
  940.                    + offsetof (PortalD, variable)));
  941. }
  942.  
  943.